home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / file.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  4KB  |  186 lines

  1. /* file - report on file type.        Author: Andy Tanenbaum */
  2.  
  3. #include <blocksize.h>
  4. #include <ar.h>
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <fcntl.h>
  8. #include <minix/config.h>
  9.  
  10. #if (CHIP == M68000)
  11. #define A_OUT        0x410    /* magic number for executables */
  12. #define A_OUT_SPLIT    0x420    /* magic number for executables split I/D */
  13. #define A_OUT_SEC    0x301    /* second check for executables */
  14. #define OBJECT        0x102    /* minix/st object */
  15. #else
  16. #define A_OUT 001401        /* magic number for executables */
  17. #define SPLIT 002040        /* second word on split I/D binaries */
  18. #endif
  19. #define XBITS 00111        /* rwXrwXrwX (x bits in the mode) */
  20. #define ENGLISH 25        /* cutoff for determining if text is Eng. */
  21. char buf[BLOCK_SIZE];
  22.  
  23. main(argc, argv)
  24. int argc;
  25. char *argv[];
  26. {
  27. /* This program uses some heuristics to try to guess about a file type by
  28.  * looking at its contents.
  29.  */
  30.  
  31.   int i;
  32.  
  33.   if (argc < 2) usage();
  34.   for (i = 1; i < argc; i++) file(argv[i]);
  35. }
  36.  
  37. file(name)
  38. char *name;
  39. {
  40.   int i, fd, n, magic, second, mode, nonascii, special, funnypct, etaoins;
  41.   int symbols;
  42.   long engpct;
  43.   char c;
  44.   struct stat st_buf;
  45.  
  46.   printf("%s: ", name);
  47.  
  48.   /* Open the file, stat it, and read in 1 block. */
  49.   fd = open(name, O_RDONLY);
  50.   if (fd < 0) {
  51.     printf("cannot open\n");
  52.     return;
  53.   }
  54.   n = fstat(fd, &st_buf);
  55.   if (n < 0) {
  56.     printf("cannot stat\n");
  57.     close(fd);
  58.     return;
  59.   }
  60.   mode = st_buf.st_mode;
  61.  
  62.   /* Check for directories and special files. */
  63.   if ((mode & S_IFMT) == S_IFDIR) {
  64.     printf("directory\n");
  65.     close(fd);
  66.     return;
  67.   }
  68.   if ((mode & S_IFMT) == S_IFCHR) {
  69.     printf("character special file\n");
  70.     close(fd);
  71.     return;
  72.   }
  73.   if ((mode & S_IFMT) == S_IFBLK) {
  74.     printf("block special file\n");
  75.     close(fd);
  76.     return;
  77.   }
  78.   n = read(fd, buf, BLOCK_SIZE);
  79.   if (n < 0) {
  80.     printf("cannot read\n");
  81.     close(fd);
  82.     return;
  83.   }
  84.  
  85.   /* Check to see if file is an archive. */
  86. #if (CHIP == M68000)
  87.   magic = (buf[0] << 8) | (buf[1] & 0377);
  88.   if (magic == 026377) {
  89. #else
  90.   magic = (buf[1] << 8) | (buf[0] & 0377);
  91.   if (magic == ARMAG) {
  92. #endif
  93.     printf("archive\n");
  94.     close(fd);
  95.     return;
  96.   }
  97. #if (CHIP == M68000)
  98.   /* Check to see if file is an object file. */
  99.   if (magic == OBJECT) {
  100.     printf("MINIX/ST object file\n");
  101.     close(fd);
  102.     return;
  103.   }
  104. #endif
  105.  
  106.   /* Check to see if file is an executable binary. */
  107. #if (CHIP != M68000)
  108.   if (magic == A_OUT) {
  109.     /* File is executable.  Check for split I/D. */
  110.     printf("MINIX/PC executable");
  111.     second = (buf[3] << 8) | (buf[2] & 0377);
  112.     if (second == SPLIT)
  113.         printf("   separate I & D space");
  114.     else
  115.         printf("   combined I & D space");
  116. #else
  117.   if (magic == A_OUT || magic == A_OUT_SPLIT) {
  118.     /* File is executable.  Check for split I/D. */
  119.     printf("MINIX/ST executable");
  120.     second = (buf[2] << 8) | (buf[3] & 0377);
  121.     if (second == A_OUT_SEC) {
  122.         if (magic == A_OUT_SPLIT)
  123.             printf("   separate I & D space");
  124.         else
  125.             printf("   combined I & D space");
  126.     }
  127. #endif
  128.     symbols = buf[28] | buf[29] | buf[30] | buf[31];
  129.     if (symbols != 0)
  130.         printf("   not stripped\n");
  131.     else
  132.         printf("   stripped\n");
  133.     close(fd);
  134.     return;
  135.   }
  136.  
  137.   /* Check to see if file is a shell script. */
  138.   if (mode & XBITS) {
  139.     /* Not a binary, but executable.  Probably a shell script. */
  140.     printf("shell script\n");
  141.     close(fd);
  142.     return;
  143.   }
  144.  
  145.   /* Check for ASCII data and certain punctuation. */
  146.   nonascii = 0;
  147.   special = 0;
  148.   etaoins = 0;
  149.   for (i = 0; i < n; i++) {
  150.     c = buf[i];
  151.     if (c & 0200) nonascii++;
  152.     if (c == ';' || c == '{' || c == '}' || c == '#') special++;
  153.     if (c == '*' || c == '<' || c == '>' || c == '/') special++;
  154.     if (c >= 'A' && c <= 'Z') c = c - 'A' + 'a';
  155.     if (c == 'e' || c == 't' || c == 'a' || c == 'o') etaoins++;
  156.     if (c == 'i' || c == 'n' || c == 's') etaoins++;
  157.   }
  158.  
  159.   if (nonascii == 0) {
  160.     /* File only contains ASCII characters.  Continue processing. */
  161.     funnypct = 100 * special / n;
  162.     engpct = 100L * (long) etaoins / n;
  163.     if (funnypct > 1) {
  164.         printf("C program\n");
  165.     } else {
  166.         if (engpct > (long) ENGLISH)
  167.             printf("English text\n");
  168.         else
  169.             printf("ASCII text\n", engpct);
  170.     }
  171.     close(fd);
  172.     return;
  173.   }
  174.  
  175.   /* Give up.  Call it data. */
  176.   printf("data\n");
  177.   close(fd);
  178.   return;
  179. }
  180.  
  181. usage()
  182. {
  183.   printf("Usage: file name ...\n");
  184.   exit(1);
  185. }
  186.